package com.sheepone.util.algorithm.math;

/**
 * @author Miss.杨
 * @description
 * @since 2024/5/17 - 10:23
 */
public class BitUtil {

    /**
     * 获取一个表示整数的最少二进制比特数
     *
     * @param val int整数
     * @return 表示整数的最少二进制比特数
     */
    public static int minBits(int val) {
        if (val < 0) {
            return 32;
        }
        int n = 0;
        while (val != 0) {
            val = val >> 1;
            n++;
        }
        return n;
    }

    /**
     * 获取一个表示整数的最少二进制比特数
     *
     * @param val long整数
     * @return 表示整数的最少二进制比特数
     */
    public static int minBits(long val) {
        if (val < 0) {
            return 64;
        }
        int n = 0;
        while (val != 0) {
            val = val >> 1;
            n++;
        }
        return n;
    }

    /**
     * 获取一个int整数的原码
     *
     * @param val int整数
     * @return 原码
     */
    public static String originalCode(int val) {
        String complementCode = complementCode(val);
        if (val < 0) {
            int index = complementCode.lastIndexOf("1");
            return "1" + "0".repeat(index - 1) + complementCode.substring(index);
        }
        return complementCode;
    }

    /**
     * 获取一个int整数的反码
     *
     * @param val int整数
     * @return 反码
     */
    public static String reverseCode(int val) {
        return complementCode(val < 0 ? val - 1 : val);
    }

    /**
     * 获取一个int整数的补码
     *
     * @param val int整数
     * @return 补码
     */
    public static String complementCode(int val) {
        String binaryString = Integer.toBinaryString(val);
        if (val < 0) {
            return binaryString;
        }
        return "0".repeat(32 - binaryString.length()) + binaryString;
    }

    /**
     * 获取一个long整数的原码
     *
     * @param val long整数
     * @return 原码
     */
    public static String originalCode(long val) {
        String complementCode = complementCode(val);
        if (val < 0) {
            int index = complementCode.lastIndexOf("1");
            return "1" + "0".repeat(index - 1) + complementCode.substring(index);
        }
        return complementCode;
    }

    /**
     * 获取一个long整数的反码
     *
     * @param val long整数
     * @return 反码
     */
    public static String reverseCode(long val) {
        return complementCode(val < 0 ? val - 1 : val);
    }

    /**
     * 获取一个long整数的补码
     *
     * @param val long整数
     * @return 补码
     */
    public static String complementCode(long val) {
        String binaryString = Long.toBinaryString(val);
        if (val < 0) {
            return binaryString;
        }
        return "0".repeat(64 - binaryString.length()) + binaryString;
    }

    public static int opposite(int val) {
        return ~val + 1;
    }


    public static long opposite(long val) {
        return ~val + 1;
    }

    /**
     * 倒转int整数最低位1
     *
     * @param val int整数
     * @return 倒转整数最低位1后的值
     */
    public static int convertLowest1(int val) {
        return val & (val - 1);
    }

    /**
     * 倒转long整数最低位1
     *
     * @param val long整数
     * @return 倒转整数最低位1后的值
     */
    public static long convertLowest1(long val) {
        return val & (val - 1);
    }

    /**
     * 倒转int整数最低位0
     *
     * @param val int整数
     * @return 倒转整数最低位0后的值
     */
    public static int convertLowest0(int val) {
        return val | (val + 1);
    }

    /**
     * 倒转long整数最低位0
     *
     * @param val long整数
     * @return 倒转整数最低位0后的值
     */
    public static long convertLowest0(long val) {
        return val | (val + 1);
    }

    /**
     * 延申int整数最低位1,如果补码为全0则变为全1
     *
     * @param val int整数
     * @return 延申int整数最低位1后的值
     */
    public static int extensionLowest1(int val) {
        return val | (val - 1);
    }

    /**
     * 延申long整数最低位1,如果补码为全0则变为全1
     *
     * @param val long整数
     * @return 延申long整数最低位1后的值
     */
    public static long extensionLowest1(long val) {
        return val | (val - 1);
    }

    /**
     * 延申int整数最低位0,如果补码为全1则变为全0
     *
     * @param val int整数
     * @return 延申int整数最低位0后的值
     */
    public static int extensionLowest0(int val) {
        return val & (val + 1);
    }

    /**
     * 延申long整数最低位0,如果补码为全1则变为全0
     *
     * @param val long整数
     * @return 延申long整数最低位0后的值
     */
    public static long extensionLowest0(long val) {
        return val & (val + 1);
    }

    /**
     * 提取int整数最低位1
     *
     * @param val int整数
     * @return 提取int整数最低位1后的值
     */
    public static int extractLowest1(int val) {
        return val & -val;
    }

    /**
     * 提取long整数最低位1
     *
     * @param val long整数
     * @return 提取long整数最低位1后的值
     */
    public static long extractLowest1(long val) {
        return val & -val;
    }

    /**
     * 提取int整数最低位0
     *
     * @param val int整数
     * @return 提取int整数最低位0后的值
     */
    public static int extractLowest0(int val) {
        // ~extractLowest0To1(val);
        return ~(~val & (val + 1));
    }

    /**
     * 提取long整数最低位0
     *
     * @param val long整数
     * @return 提取long整数最低位0后的值
     */
    public static long extractLowest0(long val) {
        // ~extractLowest0To1(val);
        return ~(~val & (val + 1));
    }

    /**
     * 提取int整数最低位0,并将其置为1
     *
     * @param val int整数
     * @return 提取int整数最低位0, 并将其置为1后的值
     */
    public static int extractLowest0To1(int val) {
        return ~val & (val + 1);
    }

    /**
     * 提取long整数最低位0,并将其置为1
     *
     * @param val long整数
     * @return 提取long整数最低位0, 并将其置为1后的值
     */
    public static long extractLowest0To1(long val) {
        return ~val & (val + 1);
    }


    /**
     * 获取[left>=0,right]的所有数的按位与值
     * 核心思想，最长公共前缀
     * @param left  左界限
     * @param right 右界限
     * @return [left, right]的所有数的按位与值
     * @problem <a href="https://leetcode.cn/problems/bitwise-and-of-numbers-range/description/?envType=study-plan-v2&envId=top-interview-150">...</a>
     */
    public static int rangeAnd(int left, int right) {
        if (left < 0) {
            throw new IllegalArgumentException("left must >= 0");
        }
        if (left == 0 || left == right) {
            return left;
        }
        while (left < right) {
            // 抹去最右边的 1
            right &= (right - 1);//right = convertLowest1(right);
        }
        return right;
    }

    public static long rangeAnd(long left, long right) {
        if (left < 0) {
            throw new IllegalArgumentException("left must >= 0");
        }
        if (left == 0 || left == right) {
            return left;
        }
        while (left < right) {
            // 抹去最右边的 1
            right &= (right - 1);//right = convertLowest1(right);
        }
        return right;
    }

    public static void main(String[] args) {
        System.out.println(complementCode(extensionLowest1(extensionLowest0(0b11111111111111111111111111111111))));
    }
}
